package com.xls.security;

import com.xls.commonutils.JwtUtils;
import com.xls.entity.SecurityUser;
import com.xls.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private JwtUtils jwtUtils;

    private String tokenHeader = "Authorization";

    private String tokenHead = "Bearer";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //拿到request中的head
        String authHeader = request.getHeader(tokenHeader);
        if (authHeader != null && authHeader.startsWith(tokenHead)) {
            // The part after "Bearer "
            String authToken = authHeader.substring(tokenHead.length());
            //解析token获取用户名
            String username = jwtUtils.getUserNameFromToken(authToken);
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                // todo 从redis中获取用户权限 done
                List<String> permissionValueList = (List<String>) redisTemplate.opsForValue().get(username);
                List<GrantedAuthority> authorities = new ArrayList<>();
                if (permissionValueList != null) {
                    for(String permissionValue : permissionValueList) {
                        if(StringUtils.isEmpty(permissionValue)) {
                            continue;
                        }
                        SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);
                        authorities.add(authority);
                    }
                }
                User user = new User();
                user.setUsername(username);
                SecurityUser securityUser = new SecurityUser(user, authorities);
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(securityUser, null, authorities);
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authentication);

                //UsernamePasswordAuthenticationToken authentication = null;
                //try {
                //    authentication = new UsernamePasswordAuthenticationToken(username, authToken, authorities);
                //} catch (Exception e) {
                //    e.printStackTrace();
                //}
                //if (authentication != null) {
                //    SecurityContextHolder.getContext().setAuthentication(authentication);
                //}

                //UserDetails userDetails = userDetailService.loadUserByUsername(username);
                //if (userDetails != null) {
                //    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                //    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                //    SecurityContextHolder.getContext().setAuthentication(authentication);
                //}
            }
        }
        filterChain.doFilter(request, response);
    }
}
